

package kr.ac.ssu.yoobh17.Omok.framework.impl;


import java.util.ArrayList;
import java.util.List;

import android.view.MotionEvent;
import android.view.View;

import kr.ac.ssu.yoobh17.Omok.framework.Input.TouchEvent;
import kr.ac.ssu.yoobh17.Omok.framework.Pool.PoolObjectFactory;
import kr.ac.ssu.yoobh17.Omok.framework.Pool;


public class MultiTouchHandler implements TouchHandler {

	boolean[]			isTouched			= new boolean[20];
	int[]				touchX				= new int[20];
	int[]				touchY				= new int[20];
	Pool<TouchEvent>	touchEventPool;
	List<TouchEvent>	touchEvents			= new ArrayList<TouchEvent>();
	List<TouchEvent>	touchEventsBuffer	= new ArrayList<TouchEvent>();
	float				scaleX;
	float				scaleY;

	public MultiTouchHandler( View view, float scaleX, float scaleY ){
		
		PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() {

			@Override
			public TouchEvent createObject() {

				return new TouchEvent();
			}
		};
		
		touchEventPool = new Pool<TouchEvent>( factory, 100 );
		view.setOnTouchListener( this );
		
		this.scaleX = scaleX;
		this.scaleY = scaleY;
		
	}
	
	@Override
	public boolean onTouch( View v, MotionEvent event ) {
		
		synchronized ( this ) {
			
			int 		action 			= event.getAction() & MotionEvent.ACTION_MASK;
			int 		pointerIndex 	= ( event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK ) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
			int 		pointerId		= event.getPointerId( pointerIndex );
			TouchEvent 	touchEvent;
			
			switch ( action ) {
			
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				
				touchEvent 				= touchEventPool.newObject();
				touchEvent.type 		= TouchEvent.TOUCH_DOWN;
				touchEvent.pointer 		= pointerId;
				touchEvent.x 			= touchX[pointerId] = (int) ( event.getX( pointerIndex ) * scaleX );
				touchEvent.y 			= touchY[pointerId] = (int) ( event.getY( pointerIndex ) * scaleY );
				isTouched[pointerId] 	= true;
				
				touchEventsBuffer.add( touchEvent );
				
				break;
				
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_CANCEL:

				touchEvent 				= touchEventPool.newObject();
				touchEvent.type 		= TouchEvent.TOUCH_UP;
				touchEvent.pointer 		= pointerId;
				touchEvent.x 			= touchX[pointerId] = (int) ( event.getX( pointerIndex ) * scaleX );
				touchEvent.y 			= touchY[pointerId] = (int) ( event.getY( pointerIndex ) * scaleY );
				isTouched[pointerId] 	= false;
				
				touchEventsBuffer.add( touchEvent );
				
				break;
				
			case MotionEvent.ACTION_MOVE:
				
				int pointerCount = event.getPointerCount();
				
				for( int i = 0 ; i < pointerCount; i++ ){
					
					pointerIndex 		= i;
					pointerId 			= event.getPointerId( pointerIndex );
					touchEvent 			= touchEventPool.newObject();
					touchEvent.type 	= TouchEvent.TOUCH_DRAGGED;
					touchEvent.pointer 	= pointerId;
					touchEvent.x 		= touchX[pointerId] = (int) ( event.getX( pointerIndex ) * scaleX );
					touchEvent.y 		= touchY[pointerId] = (int) ( event.getY( pointerIndex ) * scaleY );

					touchEventsBuffer.add( touchEvent );
					
				}
				
				break;

			}
			
			return true;
		}
	}

	@Override
	public boolean isTouchDown( int pointer ) {
		
		synchronized ( this ) {
		
			if( 0 > pointer || 20 <= pointer ){
				
				return false;
			}
			else{
				
				return isTouched[pointer];
			}
		}
	}

	@Override
	public int getTouchX( int pointer ) {

		synchronized ( this ) {
		
			if( 0 > pointer || 20 <= pointer ){
				
				return 0;
			}
			else{
				
				return touchX[pointer];
			}
		}
	}

	@Override
	public int getTouchY( int pointer ) {

		synchronized ( this ) {
		
			if( 0 > pointer || 20 <= pointer ){
				
				return 0;
			}
			else{
				
				return touchY[pointer];
			}
		}
	}

	@Override
	public List<TouchEvent> getTouchEvents() {

		synchronized ( this ) {
		
			int len = touchEvents.size();
			
			for( int i = 0; i < len; i++ ){
				
				touchEventPool.free( touchEvents.get( i ) );
				
			}
			
			touchEvents.clear();
			touchEvents.addAll( touchEventsBuffer );
			touchEventsBuffer.clear();
			
			return touchEvents;
		}
	}

}
